import os
import re
import time
import shutil

from PyQt4 import QtGui

from globals import *

class PlayFrame(QtGui.QFrame):
  def __init__(self, parent):
    QtGui.QFrame.__init__(self, parent)
    self.mplayer = None
    self.vid_w = None
    self.vid_h = None
    self.file_name = None
    self.key_funcs = {}
    self.show_delete = False
    self.show_search = False
    self.show_name = False
    self.loop_state = None
    self.loop_times = {}
    self.repeat_movie = False
    
    self.loop_timer= QtCore.QTimer(self)
    QtCore.QObject.connect(self.loop_timer, QtCore.SIGNAL("timeout()"), self.loop_seek)
    
    self.labellayout = QtGui.QVBoxLayout(self)
    self.input = QtGui.QLineEdit(self)
    self.label = QtGui.QLabel(self)
    self.x11 = QtGui.QX11EmbedContainer(self)
    
    self.setPalette(PBLACK)
    self.setAutoFillBackground(True)
    self.labellayout.addWidget(self.label)
    self.labellayout.addWidget(self.input)
    QtCore.QObject.connect(self.input, QtCore.SIGNAL("returnPressed()"), self.search)
    self.input.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed))
    self.label.hide()
    self.input.hide()
    self.input.setEnabled(False)
    self.label.setPalette(PDGRAY)
    self.init_keys()

  def init_keys(self):
    self.key_funcs[QtCore.Qt.Key_Less] = self.new_movie
    self.key_funcs[QtCore.Qt.Key_Greater] = self.new_movie
    self.key_funcs[QtCore.Qt.Key_D] = self.delete_current_movie
    self.key_funcs[QtCore.Qt.Key_Escape] = self.cancel
    self.key_funcs[QtCore.Qt.Key_S] = self.search
    self.key_funcs[QtCore.Qt.Key_W] = self.osd_name
    self.key_funcs[QtCore.Qt.Key_R] = self.repeat
    self.key_funcs[QtCore.Qt.Key_L] = self.loop
    self.key_funcs[QtCore.Qt.Key_F9] = self.begin_minus
    self.key_funcs[QtCore.Qt.Key_F10] = self.begin_plus
    self.key_funcs[QtCore.Qt.Key_F11] = self.end_minus
    self.key_funcs[QtCore.Qt.Key_F12] = self.end_plus
    self.key_funcs[QtCore.Qt.Key_U] = self.increase_var
    self.key_funcs[QtCore.Qt.Key_J] = self.lower_var

  def play(self, options, movies):
    self.mplayer = QtCore.QProcess(self)
    #self.mplayer.setStandardErrorFile('/tmp/se') 
    QtCore.QObject.connect(self.mplayer, QtCore.SIGNAL("readyReadStandardOutput ()"), self.read_so)
    wid = self.x11.winId()
    args = QtCore.QStringList()
    args.append("-wid")
    args.append(str(wid))
    args.append("-slave")
    args.append("-quiet")
    args.append("-softvol")
    args.append("-shuffle")
    for o in options:
      args.append(o)
    #args.append("-vo x11")
    for m in self.build_movielist(movies):
      args.append(m)
    self.mplayer.start(MPLAYER_BIN, args)
    self.mplayer.waitForStarted()
    self.mplayer.write("get_property aspect\n")

  def build_movielist(self, movies):
    m = []
    for mov in movies:
      if os.path.isfile(mov):
        m.append(mov)
      elif os.path.isdir(mov):
        for root, dirs, files in os.walk(mov):
          for f in files:
            m.append(os.path.join(root, f))
    return m

  def new_movie(self):
    if self.mplayer != None:
      self.loop_stop()
      self.mplayer.write("mute 0\n")
      self.mplayer.write("pt_step 1\n")
      self.mplayer.write("get_property aspect\n")
      
  def delete_current_movie(self):
    if self.mplayer != None and self.show_delete and self.file_name != None:
      if os.path.isfile(self.file_name):
        os.symlink(self.file_name, os.path.join('./Trash', os.path.basename(self.file_name)))
      self.new_movie()
      self.show_delete = False
      self.file_name = None
      self.x11.show()
      self.label.hide()
    elif self.mplayer != None and not self.show_delete:
      self.mplayer.write("pausing get_property path\n")
      self.show_delete = True
      
  def cancel(self):
    if self.mplayer != None and self.show_delete and self.file_name != None:
      self.mplayer.write("pause \n")
      self.show_delete = False
      self.file_name = None
      self.x11.show()
      self.label.hide()
    if self.show_search:
      self.label.hide()
      self.input.hide()
      self.input.setEnabled(False)
      self.show_search = False
      if self.mplayer != None:
        self.mplayer.write("pause \n")
        self.x11.show()
      
  def search(self):
    if self.show_search: 
      self.quit()
      m = []
      prefix = self.input.text()
      for sdir in SEARCH_DIRS:
        for root, dirs, files in os.walk(sdir):
          for f in files:
            if f.startswith(prefix):
              m.append(os.path.join(root, f))
      if len(m) > 0:
        self.loop_stop()
        self.load_playlist(((), m))
      self.show_search = False
      self.input.setEnabled(False)
      self.input.hide()
      self.label.hide()
      self.x11.show()
    elif not self.show_search:
      if self.mplayer != None:
        self.mplayer.write("pause\n")
        self.x11.hide()
      self.show_search = True
      self.label.setText(SEARCH_FILE_TEXT)
      self.label.show()
      self.input.show()
      self.input.setEnabled(True)
      self.input.setFocus()

  def osd_name(self):
    self.mplayer.write("get_property path\n")
    self.show_name = True
    
  def repeat(self):
    self.mplayer.write("get_property path\n")
    self.repeat_movie = True
    
  def loop(self):
    if self.mplayer == None:
      return
    if self.loop_state == None:
      self.mplayer.write("get_time_pos\n")
      self.loop_state = "GET_FIRST"
    elif self.loop_state == "GET_FIRST":
      self.mplayer.write("get_time_pos\n")
      self.loop_state = "GET_SECOND"
    elif self.loop_state == "GET_SECOND":
      print "FOOBAR - Should never get here!!!"
    elif self.loop_state == "LOOPING":
      self.mplayer.write("osd_show_text 'Finished looping' 5000\n")
      self.loop_stop()
      
  def loop_stop(self):
      self.loop_state = None
      self.loop_times['BEGIN'] = 0
      self.loop_times['END'] = 0
      self.loop_timer.stop()
  
  def loop_seek(self):
    self.mplayer.write("get_time_pos\n")

  def begin_minus(self):
    self.mplayer.write("osd_show_text 'begin -%f' 5000\n" % INTERVAL_DELTA)
    self.loop_times['BEGIN'] -= INTERVAL_DELTA

  def begin_plus(self):
    self.mplayer.write("osd_show_text 'begin +%f' 5000\n" % INTERVAL_DELTA)
    self.loop_times['BEGIN'] += INTERVAL_DELTA

  def end_minus(self):
    self.mplayer.write("osd_show_text 'end -%f'\n 5000" % INTERVAL_DELTA)
    self.loop_times['END'] -= INTERVAL_DELTA

  def end_plus(self):
    self.mplayer.write("osd_show_text 'end +%f'\n 5000" % INTERVAL_DELTA)
    self.loop_times['END'] += INTERVAL_DELTA

  def pos_x11(self, x, y, w, h):
    self.x11.setGeometry(x, y, w, h)

  def increase_var(self):
    self.vid_aspect -= VAR_CHANGE_STEP
    self.set_mplayer_res()

  def lower_var(self):
    self.vid_aspect += VAR_CHANGE_STEP
    self.set_mplayer_res()


  def hit_key(self, code):
    if code in FRAME_KEYS:
      if self.mplayer != None and FRAME_KEYS[code] != None:
        self.mplayer.write(FRAME_KEYS[code])
    if code in PLAYLIST:
      self.load_playlist(PLAYLIST[code])
    if code in self.key_funcs:
      self.key_funcs[code]()

  def load_playlist(self, pl):
    if self.mplayer != None:
      self.loop_stop()
      self.mplayer.terminate()
    self.play(pl[0], pl[1])

  def set_mplayer_res(self):
    sw = self.width()
    sh = self.height()
    sar = float(sw) / float(sh)
    var = self.vid_aspect
    if sar > var:
      #center on x axis
      vh = sh
      vw = int(vh * var)
      vx = int((sw - vw) / 2)
      vy = 0
    else:
      #center on y axis
      vw = sw
      vh = int(vw / var)
      vx = 0
      vy = int((sh - vh) / 2)
    self.pos_x11(vx, vy, vw, vh)

  def read_so(self):
    line = self.mplayer.readLine(128)
    while line != None and line != "":
      self.check_aspect_answer(line)
      self.check_res_answer(line)
      self.check_file_name_answer(line)
      self.check_time_pos(line)
      line = self.mplayer.readLine(128)

  def check_res_answer(self, line):
    regexp = re.compile(r"""
        ^ANS_VIDEO_RESOLUTION='
        (?P<w>\d+)
        [ x]+
        (?P<h>\d+)
        .*
        """, re.VERBOSE)
    match = regexp.match(line)
    if match != None:
      self.vid_w = int(match.group('w'))
      self.vid_h = int(match.group('h'))
      self.vid_aspect = float(self.vid_w) / float(self.vid_h)
      self.set_mplayer_res()

      
  def check_aspect_answer(self, line):
    regexp = re.compile(r"""
        ^ANS_aspect=
        (?P<aspect>.+)
        """, re.VERBOSE)
    match = regexp.match(line)
    if match != None:
      self.vid_aspect = float(match.group('aspect'))
      if self.vid_aspect == 0:
        self.mplayer.write("get_video_resolution\n")
      else:
        self.set_mplayer_res()
  
  
  def check_file_name_answer(self, line):
    regexp = re.compile(r"""
        ^ANS_path=
        (?P<path>.+)
        """, re.VERBOSE)
    match = regexp.match(line)
    if match != None:
      self.file_name = str(match.group('path'))
      if self.show_delete:
        self.x11.hide()
        self.label.setText(DELETE_FILE_TEXT % self.file_name)
        self.label.show()
      if self.show_name:
        self.show_name = False
        self.mplayer.write("osd_show_text '%s' 5000\n" % self.file_name)
        self.file_name = None
      if self.repeat_movie:
        self.repeat_movie = False
        self.mplayer.write("osd_show_text 'Repeat: %s' 5000\n" % self.file_name)
        playlist = (('-loop', '0'), (self.file_name,)) 
        self.load_playlist(playlist)
        self.file_name = None
  
  def check_time_pos(self, line):
    regexp = re.compile(r"""
        ^ANS_TIME_POSITION=
        (?P<tp>.+)
        """, re.VERBOSE)
    match = regexp.match(line)
    if match != None:
      tp = int(float(match.group('tp')))
      if self.loop_state == None:
        print "Oops, should never get here..."
      elif self.loop_state == "GET_FIRST":
        self.loop_times['BEGIN'] = tp
        self.mplayer.write("osd_show_text 'Begin loop' 5000\n")
      elif self.loop_state == "GET_SECOND":
        self.loop_times['END'] = tp
        self.mplayer.write("osd_show_text 'End loop' 5000\n")
        self.loop_state = "LOOPING"
        self.loop_timer.start(1000)
      elif self.loop_state == "LOOPING":
        if tp > self.loop_times['END']:
          self.mplayer.write("seek %d 2\n" % (self.loop_times['BEGIN']))
          QtCore.QThread.sleep(1)

  def decrackle(self):
    self.mplayer.write("pause\n")
    self.mplayer.write("pause\n")
        
  def quit(self):
    if self.mplayer != None:
      self.x11.discardClient()
      self.mplayer.write("pause\n")
      self.mplayer.write("quit\n")
      self.mplayer.waitForFinished()
      self.mplayer = None

  def resizeEvent(self, event):
    #self.label.setGeometry(0, 0, event.size().width(), event.size().height())
    if self.mplayer != None:
      self.set_mplayer_res()
